package com.oig.sys.security.util;

import com.oig.common.exception.ErrorCodeEnum;
import com.oig.common.exception.ServiceException;
import com.oig.sys.security.config.CacheConstants;
import com.oig.sys.security.support.SecurityUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

@Slf4j
public class SecurityUtil {

    private final static SecurityUser sys = new SecurityUser(0,"0000","sys","系统自动","sys","",1, "UCHAIN平台管理",null,0,"S0","系统服务",new ArrayList<>());

    /**
     * 获取Authentication
     */
    public static Authentication getAuthentication() {
        return SecurityContextHolder.getContext().getAuthentication();
    }

    /**
     * 获取用户
     */
    public static SecurityUser getUser(Authentication authentication) {
        Object principal = authentication.getPrincipal();
        //log.debug("principal:{}", principal);
        if (principal instanceof SecurityUser){
            return (SecurityUser) principal;
        } else if (principal instanceof String){    //凭证模式，如果调用，返回系统用户操作? 凭证模式不应该给操作更新数据，只查询？
            return sys;
        }
        return null;
    }

    /**
     * 获取用户
     */
    public static SecurityUser getUser() {
        Authentication authentication = getAuthentication();
        if (authentication == null) {
            return null;
        }
        return getUser(authentication);
    }



    public static SecurityUser getDefineUserMain(){
        SecurityUser securityUser = getUser();
        //log.debug("user:{}", securityUser);
        if (securityUser ==null){
            throw new ServiceException(ErrorCodeEnum.SYSTEM_ERROR);
        }
        return securityUser;
    }


    public static SecurityUser getSys(){
        return sys;
    }

    /**
     * 临时支持
     */
    public static SecurityUser getUserForIfNullBuild(){
        SecurityUser securityUser = getUser();
        if (securityUser == null){
            return sys;
        }
        return securityUser;
    }



    public static SecurityUser changeUser(Map<?, ?> map){
        Collection<? extends GrantedAuthority> authorities = getAuthorities(map);
        Integer id = (Integer) map.get(CacheConstants.USER_ID);
        String code = map.get(CacheConstants.USER_CODE)==null?null:(String) map.get(CacheConstants.USER_CODE);
        String username = (String) map.get(CacheConstants.USER_NAME);
        String nickName = map.get(CacheConstants.USER_NICK_NAME)==null?null:(String) map.get(CacheConstants.USER_NICK_NAME);
        String realName = map.get(CacheConstants.USER_REAL_NAME)==null?null:(String) map.get(CacheConstants.USER_REAL_NAME);
        Integer defaultSysId = map.get(CacheConstants.USER_DEF_SYS)==null?null:(Integer) map.get(CacheConstants.USER_DEF_SYS);
        String defaultSysName = map.get(CacheConstants.USER_DEF_SYS_NAME)==null?null:(String) map.get(CacheConstants.USER_DEF_SYS_NAME);
        String defaultSysImgUrl = map.get(CacheConstants.USER_DEF_SYS_IMGURL)==null?null:(String) map.get(CacheConstants.USER_DEF_SYS_IMGURL);
        Integer tenantId = map.get(CacheConstants.USER_TENANT_ID)==null?null:(Integer)map.get(CacheConstants.USER_TENANT_ID);
        String tenantCode = map.get(CacheConstants.USER_TENANT_CODE)==null?null:(String)map.get(CacheConstants.USER_TENANT_CODE);
        String tenantName = map.get(CacheConstants.USER_TENANT_NAME)==null?null:(String)map.get(CacheConstants.USER_TENANT_NAME);
        return new SecurityUser(id, code, nickName,realName, username, CacheConstants.N_A,
                defaultSysId, defaultSysName, defaultSysImgUrl, tenantId, tenantCode, tenantName, authorities);
    }

    public static Collection<? extends GrantedAuthority> getAuthorities(Map<?, ?> map) {
        Object authorities = map.get("authorities");
        if (authorities instanceof String) {
            return AuthorityUtils.commaSeparatedStringToAuthorityList((String) authorities);
        }
        if (authorities instanceof List) {
            List<?>  aList = (List<?>) authorities ;
            List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
            aList.forEach(a -> {
                if (a instanceof Map) {
                    Map<?,?> as = ( Map<?,?>) a ;
                    as.forEach( (k,v)-> grantedAuthorities.add(new SimpleGrantedAuthority(String.valueOf(v))) );
                }
            });
            return grantedAuthorities;
        }
        throw new IllegalArgumentException("Authorities must be either a String or a Collection");
    }

}
